'use client';

import { useRouter } from 'next/navigation';
import { useActionState, useEffect, useState, useTransition } from 'react';
import { FoxButton } from '@fox/core/components/fox-button';
import { FoxButtonGroup } from '@fox/core/components/fox-button-group';
import { FoxButtonPanel } from '@fox/core/components/fox-button-panel';
import { FoxCard } from '@fox/core/components/fox-card';
import { FoxDescriptionList } from '@fox/core/components/fox-description-list';
import { FoxHelperText } from '@fox/core/components/fox-helper-text';
import { FoxInput } from '@fox/core/components/fox-input';
import { FoxPageHeader } from '@fox/core/components/fox-page-header';
import { FoxSelect } from '@fox/core/components/fox-select';
import { openPostcodeSearch } from '@/app/_components/postcode';
import { submitFormAction } from '@/app/_hooks/submit-form-action';
import { useBlockingAction } from '@/app/_hooks/use-blocking-action';
import { useFeedback } from '@/app/_hooks/use-feedback';
import type { CommonCode } from '@/lib/domain/common-code';
import {
  MERCHANT_DETAIL_VISIBILITY_OPTIONS,
  MERCHANT_VOUCHER_USE_OPTIONS,
  formatMerchantDetailStatusLabel,
  formatOptionalValue,
  type MerchantDetail,
  type MerchantDetailSummary,
} from '@/lib/domain/merchant-detail';
import {
  ADDRESS_MAX_LENGTH,
  CLOSED_DAYS_MAX_LENGTH,
  DESCRIPTION_MAX_LENGTH,
  INITIAL_MERCHANT_DETAIL_FORM_STATE,
  MERCHANT_NAME_MAX_LENGTH,
  SORT_ORDER_MAX,
} from '@/lib/domain/merchant-detail-form';
import { MERCHANT_DETAILS_PATH, merchantDetailPath } from '@/lib/domain/merchant-detail-query';
import type { MerchantProduct } from '@/lib/domain/merchant-product';
import {
  deleteMerchantDetailAction,
  saveMerchantDetailAction,
  updateMerchantDetailVisibilityAction,
} from '../../_actions';
import { MerchantChoiceChips } from '../../_components/merchant-choice-chips';
import { MerchantImageField } from '../../_components/merchant-image-field';
import { MerchantProductTable } from '../../_components/merchant-product-table';
import styles from './merchant-detail-form.module.scss';

interface MerchantDetailFormProps {
  /** 상세가 있는 가맹점 — 고친다. */
  detail?: MerchantDetail;
  /** 상세가 아직 없는데 가맹점은 있는 경우(행의 [수정]) — 그 가맹점에 처음 만든다. */
  merchant?: MerchantDetailSummary;
  products?: MerchantProduct[];
  categories: CommonCode[];
  /** 메뉴 표의 배지 코드표(`FRCS_BADGE_CD`). */
  badgeCodes?: CommonCode[];
}

/**
 * 가맹몰 상세 — 기획 BO-MAL-002(등록)·003(수정)을 한 화면으로 합쳤다(사용자 확정). `detail`이 있으면
 * 고치고, `merchant`면 그 가맹점에 처음 만들고, 둘 다 없으면 업체(가맹점)부터 새로 만든다.
 * 첫 저장 뒤에는 그 가맹점 주소로 옮겨 가되 화면 구성은 그대로라 바로 메뉴를 붙일 수 있고, 이후
 * 저장은 그 자리에 머문다.
 *
 * 업체명·연락처·우편번호·주소는 여기서 직접 입력한다(사용자 확정) — 저장하면 액션이 가맹점을
 * 만들거나(코드 없음) 바뀐 값을 고친(코드 있음) 뒤 상세를 붙인다. 바뀌었는지는 숨은 원본 값과 비교한다.
 */
export function MerchantDetailForm({
  detail,
  merchant: fixedMerchant,
  products = [],
  categories,
  badgeCodes = [],
}: MerchantDetailFormProps) {
  const router = useRouter();
  const { showAlert, hideAlert, showToast } = useFeedback();
  const [isBusy, startAction] = useBlockingAction();
  const [state, formAction, isPending] = useActionState(
    saveMerchantDetailAction,
    INITIAL_MERCHANT_DETAIL_FORM_STATE
  );
  const isEdit = detail !== undefined;
  const errors = state.status === 'error' ? (state.errors ?? {}) : {};

  // 가맹점이 있으면(상세가 있든 없든) 그 코드로 고치고, 없으면 빈 코드로 보내 새로 만든다.
  const merchant: MerchantDetailSummary | null = detail ?? fixedMerchant ?? null;
  const frcsNo = merchant?.id ?? '';
  const original = {
    name: merchant?.name ?? '',
    phoneNumber: merchant?.phoneNumber ?? '',
    postalCode: merchant?.postalCode ?? '',
    address: merchant?.address ?? '',
    addressDetail: merchant?.addressDetail ?? '',
  };
  // 우편번호·주소는 검색으로 채우거나 직접 고친다.
  const [postalCode, setPostalCode] = useState(original.postalCode);
  const [address, setAddress] = useState(original.address);
  const [isSearching, startSearching] = useTransition();
  const [categoryCode, setCategoryCode] = useState(detail?.categoryCode ?? '');
  const [visibility, setVisibility] = useState<string[]>([
    detail?.isVisible === false ? 'N' : 'Y',
  ]);
  const [voucherUse, setVoucherUse] = useState<string[]>(['Y']);

  useEffect(() => {
    if (state.status !== 'success') return;
    if (state.created) {
      showToast({ variant: 'success', message: '등록했습니다. 이어서 메뉴를 추가할 수 있습니다.' });
      router.replace(merchantDetailPath(state.frcsNo));
    } else {
      showToast({ variant: 'success', message: '저장했습니다.' });
      router.refresh();
    }
  }, [state, router, showToast]);

  /** 기획 BO-MAL-002 [주소 검색] — 고른 주소로 우편번호·주소를 채운다. */
  function searchAddress() {
    startSearching(async () => {
      let picked;
      try {
        picked = await openPostcodeSearch();
      } catch {
        showToast({ variant: 'danger', message: '주소 검색을 불러오지 못했습니다. 잠시 후 다시 시도해 주세요.' });
        return;
      }
      if (!picked) return;
      setPostalCode(picked.zonecode);
      setAddress(picked.address);
    });
  }

  function toggleVisibility() {
    if (!detail) return;
    const next = detail.isVisible === false;
    startAction(async () => {
      const result = await updateMerchantDetailVisibilityAction(detail.id, next);
      showToast(
        result.status === 'error'
          ? { variant: 'danger', message: result.message }
          : { variant: 'success', message: next ? '노출로 바꿨습니다.' : '비활성으로 바꿨습니다.' }
      );
    });
  }

  function runDelete() {
    if (!detail) return;
    hideAlert();
    startAction(async () => {
      const result = await deleteMerchantDetailAction(detail.id);
      if (result.status === 'error') {
        showToast({ variant: 'danger', message: result.message });
        return;
      }
      showToast({ variant: 'success', message: '삭제했습니다.' });
      router.push(MERCHANT_DETAILS_PATH);
    });
  }

  function confirmDelete() {
    if (!detail) return;
    showAlert({
      variant: 'danger',
      title: '가맹몰 상세를 삭제하시겠습니까?',
      message: `"${detail.name}"의 상세 정보를 삭제합니다. 삭제 후에는 되돌릴 수 없습니다.`,
      actions: (
        <FoxButtonGroup size="md">
          <FoxButton type="default" size="md" label="취소" onAction={hideAlert} />
          <FoxButton type="primary" size="md" label="삭제" onAction={runDelete} />
        </FoxButtonGroup>
      ),
    });
  }

  return (
    <>
      <FoxPageHeader
        title="가맹몰 상세 정보"
        description="지역상생몰에 노출할 업체의 상세를 등록·수정한다. 저장 즉시 앱에 반영된다"
        breadcrumb={[
          { label: '홈', href: '/' },
          { label: '관리자관리' },
          { label: '가맹몰 상세 관리', href: MERCHANT_DETAILS_PATH },
          { label: '상세 정보' },
        ]}
      />

      <form
        id="merchant-detail-form"
        onSubmit={(event) => submitFormAction(event, formAction)}
        className={styles.form}
      >
        <input type="hidden" name="frcsNo" value={frcsNo} />
        <input type="hidden" name="mode" value={isEdit ? 'edit' : 'create'} />
        {/* 저장 시 업체 값이 바뀌었는지 비교할 원본 — 안 바뀌었으면 가맹점 수정 요청을 보내지 않는다. */}
        <input type="hidden" name="originalname" value={original.name} />
        <input type="hidden" name="originalphoneNumber" value={original.phoneNumber} />
        <input type="hidden" name="originalpostalCode" value={original.postalCode} />
        <input type="hidden" name="originaladdress" value={original.address} />
        <input type="hidden" name="originaladdressDetail" value={original.addressDetail} />

        <FoxCard size="lg" title="기본 정보" className={styles.section}>
          <div className={styles.grid}>
            <div className={styles.fieldWide}>
              <FoxInput
                size="md"
                name="name"
                label="업체명"
                requirement="required"
                placeholder="예) 타볼라타"
                defaultValue={original.name}
                maxLength={MERCHANT_NAME_MAX_LENGTH}
                invalid={Boolean(errors.name)}
                message={errors.name}
              />
            </div>
            <div className={styles.field}>
              <FoxSelect
                size="md"
                label="카테고리"
                requirement="required"
                placeholder="선택"
                options={categories.map((code) => ({ value: code.code, label: code.label }))}
                value={categoryCode}
                onValueChange={setCategoryCode}
                error={Boolean(errors.categoryCode)}
              />
              <input type="hidden" name="categoryCode" value={categoryCode} />
              {errors.categoryCode && <FoxHelperText type="danger" message={errors.categoryCode} />}
            </div>
            <div className={styles.field}>
              <FoxInput
                size="md"
                name="phoneNumber"
                label="업체 연락처"
                requirement="required"
                placeholder="0507-1413-6625"
                defaultValue={original.phoneNumber}
                invalid={Boolean(errors.phoneNumber)}
                message={errors.phoneNumber}
              />
            </div>
          </div>

          <div className={styles.grid}>
            <div className={styles.fieldNarrow}>
              <FoxInput
                size="md"
                name="postalCode"
                label="우편번호"
                requirement="required"
                placeholder="00000"
                value={postalCode}
                onChange={setPostalCode}
                invalid={Boolean(errors.postalCode)}
                message={errors.postalCode}
              />
            </div>
            <div className={styles.searchButton}>
              <FoxButton
                type="default"
                size="md"
                label={isSearching ? '검색 중...' : '주소 검색'}
                disabled={isSearching}
                onAction={searchAddress}
              />
            </div>
            <div className={styles.fieldWide}>
              <FoxInput
                size="md"
                name="address"
                label="주소"
                placeholder="도로명 주소 (검색 결과 자동 입력)"
                value={address}
                onChange={setAddress}
                maxLength={ADDRESS_MAX_LENGTH}
                invalid={Boolean(errors.address)}
                message={errors.address}
              />
            </div>
            <div className={styles.field}>
              <FoxInput
                size="md"
                name="addressDetail"
                label="상세주소"
                placeholder="건물명 · 층 · 호"
                defaultValue={original.addressDetail}
                maxLength={ADDRESS_MAX_LENGTH}
              />
            </div>
          </div>

          <div className={styles.grid}>
            <div className={styles.fieldWide}>
              <FoxInput
                size="md"
                name="description"
                label="한줄 소개"
                placeholder="앱 목록·상세에 노출되는 한 줄 설명"
                defaultValue={detail?.description ?? ''}
                maxLength={DESCRIPTION_MAX_LENGTH}
                invalid={Boolean(errors.description)}
                message={errors.description}
              />
            </div>
            <div className={styles.fieldNarrow}>
              <FoxInput
                size="md"
                name="openTime"
                type="time"
                label="영업 시작"
                defaultValue={detail?.openTime ?? ''}
                invalid={Boolean(errors.openTime)}
                message={errors.openTime}
              />
            </div>
            <div className={styles.fieldNarrow}>
              <FoxInput
                size="md"
                name="closeTime"
                type="time"
                label="영업 종료"
                defaultValue={detail?.closeTime ?? ''}
                invalid={Boolean(errors.closeTime)}
                message={errors.closeTime}
              />
            </div>
            <div className={styles.field}>
              <FoxInput
                size="md"
                name="closedDays"
                label="휴무일"
                placeholder="예) 매주 월요일"
                defaultValue={detail?.closedDays ?? ''}
                maxLength={CLOSED_DAYS_MAX_LENGTH}
                invalid={Boolean(errors.closedDays)}
                message={errors.closedDays}
              />
            </div>
          </div>

          <div className={styles.grid}>
            <MerchantChoiceChips
              label="노출 상태"
              name="isVisible"
              required
              options={MERCHANT_DETAIL_VISIBILITY_OPTIONS}
              values={visibility}
              onChange={setVisibility}
            />
            <MerchantChoiceChips
              label="바우처 사용"
              name="isVoucherUsable"
              required
              options={MERCHANT_VOUCHER_USE_OPTIONS}
              values={voucherUse}
              onChange={setVoucherUse}
            />
            <div className={styles.fieldNarrow}>
              <FoxInput
                size="md"
                name="sortOrder"
                type="number"
                inputMode="numeric"
                min={0}
                max={SORT_ORDER_MAX}
                label="노출 순서"
                placeholder="숫자 (낮을수록 상단)"
                defaultValue={detail?.sortOrder == null ? '' : String(detail.sortOrder)}
                invalid={Boolean(errors.sortOrder)}
                message={errors.sortOrder}
              />
            </div>
          </div>
        </FoxCard>

        <FoxCard
          size="lg"
          title="이미지 등록"
          description="대표 1장 필수 · 추가 최대 11장 (앱 슬라이더 최대 12장)"
          className={styles.section}
        >
          {/* 저장으로 파일 id나 장수가 바뀌면 다시 마운트해 칸 상태를 서버 값으로 되돌린다 —
              덧붙이기 저장은 id가 그대로라 장수로 알아챈다. */}
          <MerchantImageField
            key={`${detail?.thumbnailFileId ?? ''}/${detail?.imageFileId ?? ''}/${detail?.imageUrls.length ?? 0}`}
            defaultThumbnailUrl={detail?.thumbnailUrl ?? null}
            retainedThumbnailId={detail?.thumbnailFileId ?? null}
            defaultImageUrls={detail?.imageUrls ?? []}
            retainedImageFileId={detail?.imageFileId ?? null}
            thumbnailError={errors.thumbnail}
            imagesError={errors.images}
          />
        </FoxCard>

        <FoxCard
          size="lg"
          title="메뉴 정보"
          description="앱 상세 화면의 메뉴 목록에 노출된다"
          className={styles.section}
        >
          <MerchantProductTable frcsNo={frcsNo} badgeCodes={badgeCodes} products={products} canAdd={isEdit} />
        </FoxCard>

        {detail && (
          <FoxCard size="lg" title="등록 정보" className={styles.section}>
            <FoxDescriptionList
              layout="inline"
              items={[
                { key: 'registeredAt', term: '등록일시', description: formatOptionalValue(detail.registeredAt) },
                { key: 'registeredBy', term: '등록자', description: formatOptionalValue(detail.registeredBy) },
                {
                  key: 'modified',
                  term: '최종 수정',
                  description: [detail.modifiedAt, detail.modifiedBy]
                    .filter((value): value is string => Boolean(value))
                    .join(' / ') || '-',
                },
                { key: 'status', term: '현재 상태', description: formatMerchantDetailStatusLabel(detail) },
              ]}
            />
          </FoxCard>
        )}

        {state.status === 'error' && state.message && (
          <FoxHelperText type="danger" message={state.message} />
        )}

        <FoxButtonPanel>
          <FoxButtonGroup size="lg">
            {detail && (
              <>
                <FoxButton type="default" size="lg" label="삭제" disabled={isBusy} onAction={confirmDelete} />
                <FoxButton
                  type="default"
                  size="lg"
                  label={detail.isVisible === false ? '노출' : '비활성'}
                  disabled={isBusy}
                  onAction={toggleVisibility}
                />
              </>
            )}
            <FoxButton
              type="default"
              size="lg"
              label="취소"
              onAction={() => router.push(MERCHANT_DETAILS_PATH)}
            />
            <FoxButton
              type="primary"
              size="lg"
              htmlType="submit"
              label={isEdit ? '저장' : '등록'}
              loading={isPending}
            />
          </FoxButtonGroup>
        </FoxButtonPanel>
      </form>
    </>
  );
}
